import { Graph, Shape } from '@antv/x6'
import { Stencil } from '@antv/x6-plugin-stencil'
import { Transform } from '@antv/x6-plugin-transform'
import { Selection } from '@antv/x6-plugin-selection'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Clipboard } from '@antv/x6-plugin-clipboard'
import { History } from '@antv/x6-plugin-history'

import { nodeData } from './default-node'
import { NodeMenuTool } from './node-menu-tool'
import type { NodeTempType } from '@/components/node-temp/node-temp'
export default class YlyDrawGraph {
  rootDom: HTMLElement
  rootGraph: Graph;
  constructor(rootDom: HTMLElement) {
    this.rootDom = rootDom
    this.rootGraph = this.initGraph(rootDom)
    this.initEventOrKey()
    this.initRegion()
  }
  initGraph(rootDom: HTMLElement) {
    const graph = new Graph({
      container: rootDom,
      grid: true,
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: 'ctrl',
        minScale: 0.5,
        maxScale: 3,
      },
      connecting: {
        router: 'manhattan',
        connector: {
          name: 'rounded',
          args: {
            radius: 8,
          },
        },
        anchor: 'center',
        connectionPoint: 'anchor',
        allowBlank: false,
        snap: {
          radius: 20,
        },
        createEdge() {
          return new Shape.Edge({
            attrs: {
              line: {
                stroke: '#A2B1C3',
                strokeWidth: 2,
                targetMarker: {
                  name: 'block',
                  width: 12,
                  height: 8,
                },
              },
            },
            zIndex: 0,
          })
        },
        validateConnection({ targetMagnet }) {
          return !!targetMagnet
        },
      },
      highlighting: {
        magnetAdsorbed: {
          name: 'stroke',
          args: {
            attrs: {
              fill: '#5F95FF',
              stroke: '#5F95FF',
            },
          },
        },
      },
    });

    // #region 使用插件
    graph
    .use(
      new Transform({
        resizing: true,
        rotating: true,
      }),
    )
    .use(
      new Selection({
        rubberband: true,
        showNodeSelectionBox: true,
      }),
    )
    .use(new Snapline())
    .use(new Keyboard())
    .use(new Clipboard())
    .use(new History())
    // #endregion

    Graph.registerNodeTool('nodeMenu', NodeMenuTool)

    graph.on('node:click', ({ node }) => {
      if(!node.hasTool('button-remove')) {
        node.addTools([
          {
            name: 'button-remove',
            args: {
              x: 0,
              y: 0,
              offset: { x: 100, y: 10 },
            },
          },
          {
            name: 'boundary',
            args: {
              padding: 5,
              attrs: {
                fill: '#7c68fc',
                stroke: '#333',
                'stroke-width': 1,
                'fill-opacity': 0.2,
              },
            },
          },
        ])
      }
    })
    graph.on('node:mouseleave', ({ node }) => {
      node.removeTools()
    })
    return graph
  }
  // 初始化快捷键和事件
  initEventOrKey() {
    // #region 快捷键与事件
    this.rootGraph.bindKey(['meta+c', 'ctrl+c'], () => {
      const cells = this.rootGraph.getSelectedCells()
      if (cells.length) {
        this.rootGraph.copy(cells)
      }
      return false
    })
    this.rootGraph.bindKey(['meta+x', 'ctrl+x'], () => {
      const cells = this.rootGraph.getSelectedCells()
      if (cells.length) {
        this.rootGraph.cut(cells)
      }
      return false
    })
    this.rootGraph.bindKey(['meta+v', 'ctrl+v'], () => {
      if (!this.rootGraph.isClipboardEmpty()) {
        const cells = this.rootGraph.paste({ offset: 32 })
        this.rootGraph.cleanSelection()
        this.rootGraph.select(cells)
      }
      return false
    })

    // undo redo
    this.rootGraph.bindKey(['meta+z', 'ctrl+z'], () => {
      if (this.rootGraph.canUndo()) {
        this.rootGraph.undo()
      }
      return false
    })
    this.rootGraph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
      if (this.rootGraph.canRedo()) {
        this.rootGraph.redo()
      }
      return false
    })

    // select all
    this.rootGraph.bindKey(['meta+a', 'ctrl+a'], () => {
      const nodes = this.rootGraph.getNodes()
      if (nodes) {
        this.rootGraph.select(nodes)
      }
    })

    // delete
    this.rootGraph.bindKey('backspace', () => {
      const cells = this.rootGraph.getSelectedCells()
      if (cells.length) {
        this.rootGraph.removeCells(cells)
      }
    })

    // zoom
    this.rootGraph.bindKey(['ctrl+1', 'meta+1'], () => {
      const zoom = this.rootGraph.zoom()
      if (zoom < 1.5) {
        this.rootGraph.zoom(0.1)
      }
    })
    this.rootGraph.bindKey(['ctrl+2', 'meta+2'], () => {
      const zoom = this.rootGraph.zoom()
      if (zoom > 0.5) {
        this.rootGraph.zoom(-0.1)
      }
    })


    // 控制连接桩显示/隐藏
    const showPorts = (ports: NodeListOf<SVGElement>, show: boolean) => {
      for (let i = 0, len = ports.length; i < len; i += 1) {
        ports[i].style.visibility = show ? 'visible' : 'hidden'
      }
    }
    this.rootGraph.on('node:mouseenter', () => {
      const container = document.getElementById('graph-container')!
      const ports = container.querySelectorAll(
        '.x6-port-body',
      ) as NodeListOf<SVGElement>
      showPorts(ports, true)
    })
    this.rootGraph.on('node:mouseleave', () => {
      const container = document.getElementById('graph-container')!
      const ports = container.querySelectorAll(
        '.x6-port-body',
      ) as NodeListOf<SVGElement>
      showPorts(ports, false)
    })
  }
  /**
   * 初始化图形
   */
  initRegion() {
    // #region 初始化图形
    // const r1 = this.rootGraph.createNode({
    //   shape: 'custom-rect',
    //   label: '开始',
    //   attrs: {
    //     body: {
    //       rx: 20,
    //       ry: 26,
    //     },
    //   },
    // })
    // const r2 = this.rootGraph.createNode({
    //   shape: 'custom-rect',
    //   label: '过程',
    // })
    // const r3 = this.rootGraph.createNode({
    //   shape: 'custom-rect',
    //   attrs: {
    //     body: {
    //       rx: 6,
    //       ry: 6,
    //     },
    //   },
    //   label: '可选过程',
    // })
    // const r4 = this.rootGraph.createNode({
    //   shape: 'custom-polygon',
    //   attrs: {
    //     body: {
    //       refPoints: '0,10 10,0 20,10 10,20',
    //     },
    //   },
    //   label: '决策',
    // })
    // const r5 = this.rootGraph.createNode({
    //   shape: 'custom-polygon',
    //   attrs: {
    //     body: {
    //       refPoints: '10,0 40,0 30,20 0,20',
    //     },
    //   },
    //   label: '数据',
    // })
    // const r6 = this.rootGraph.createNode({
    //   shape: 'custom-circle',
    //   label: '连接',
    // })

    
    const imageShapes = [
      {
        label: 'Client',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/687b6cb9-4b97-42a6-96d0-34b3099133ac.svg',
      },
      {
        label: 'Http',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/dc1ced06-417d-466f-927b-b4a4d3265791.svg',
      },
      {
        label: 'Api',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/c55d7ae1-8d20-4585-bd8f-ca23653a4489.svg',
      },
      {
        label: 'Sql',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg',
      },
      {
        label: 'Clound',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/c36fe7cb-dc24-4854-aeb5-88d8dc36d52e.svg',
      },
      {
        label: 'Mq',
        image:
          'https://gw.alipayobjects.com/zos/bmw-prod/2010ac9f-40e7-49d4-8c4a-4fcf2f83033b.svg',
      },
    ]
    const imageNodes = imageShapes.map((item) =>
      this.rootGraph.createNode({
        shape: 'custom-image',
        label: item.label,
        attrs: {
          image: {
            'xlink:href': item.image,
          },
        },
      }),
    )
  }
  
  renderGraph() {
    this.rootGraph.fromJSON(nodeData)
  }

   //添加节点到画布
  addHandleNode(x: number, y: number, id: string, nodeTemp: NodeTempType) {
    this.rootGraph.addNode({
      id: id,
      shape: nodeTemp.name, // 指定使用何种图形，默认值为 'rect'
      x: x,
      y: y,
      width: 60,
      height: 60,
      // imageUrl: image,
      attrs: {
        body: {
          stroke: "#ffa940",
          fill: "#ffd591",
        },
        label: {
          textWrap: {
            width: 90,
            text: nodeTemp.label,
          },
          fill: "black",
          fontSize: 12,
          refX: 0.5,
          refY: "100%",
          refY2: 4,
          textAnchor: "middle",
          textVerticalAnchor: "top",
        },
      },
      ports: {
        groups: {
          group1: {
            position: [30, 30],
          },
        },
        items: [
          {
            group: "group1",
            id: "port1",
            attrs: {
              circle: {
                r: 6,
                magnet: true,
                stroke: "#ffffff",
                strokeWidth: 2,
                fill: "#5F95FF",
              },
            },
          },
        ],
      },
      zIndex: 10,
    });
  }
}

const registerNode = () => {
  const ports = {
    groups: {
      top: {
        position: 'top',
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: '#5F95FF',
            strokeWidth: 1,
            fill: '#fff',
            style: {
              visibility: 'hidden',
            },
          },
        },
      },
      right: {
        position: 'right',
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: '#5F95FF',
            strokeWidth: 1,
            fill: '#fff',
            style: {
              visibility: 'hidden',
            },
          },
        },
      },
      bottom: {
        position: 'bottom',
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: '#5F95FF',
            strokeWidth: 1,
            fill: '#fff',
            style: {
              visibility: 'hidden',
            },
          },
        },
      },
      left: {
        position: 'left',
        attrs: {
          circle: {
            r: 4,
            magnet: true,
            stroke: '#5F95FF',
            strokeWidth: 1,
            fill: '#fff',
            style: {
              visibility: 'hidden',
            },
          },
        },
      },
    },
    items: [
      {
        group: 'top',
      },
      {
        group: 'right',
      },
      {
        group: 'bottom',
      },
      {
        group: 'left',
      },
    ],
  }

  Graph.registerNode(
    'custom-rect',
    {
      inherit: 'rect',
      width: 66,
      height: 36,
      attrs: {
        body: {
          strokeWidth: 1,
          stroke: '#5F95FF',
          fill: '#EFF4FF',
        },
        text: {
          fontSize: 12,
          fill: '#262626',
        },
      },
      ports: { ...ports },
    },
    true,
  )

  Graph.registerNode(
    'custom-polygon',
    {
      inherit: 'polygon',
      width: 66,
      height: 36,
      attrs: {
        body: {
          strokeWidth: 1,
          stroke: '#5F95FF',
          fill: '#EFF4FF',
        },
        text: {
          fontSize: 12,
          fill: '#262626',
        },
      },
      ports: {
        ...ports,
        items: [
          {
            group: 'top',
          },
          {
            group: 'bottom',
          },
        ],
      },
    },
    true,
  )

  Graph.registerNode(
    'custom-circle',
    {
      inherit: 'circle',
      width: 45,
      height: 45,
      attrs: {
        body: {
          strokeWidth: 1,
          stroke: '#5F95FF',
          fill: '#EFF4FF',
        },
        text: {
          fontSize: 12,
          fill: '#262626',
        },
      },
      ports: { ...ports },
    },
    true,
  )

  Graph.registerNode(
    'custom-image',
    {
      inherit: 'rect',
      width: 52,
      height: 52,
      markup: [
        {
          tagName: 'rect',
          selector: 'body',
        },
        {
          tagName: 'image',
        },
        {
          tagName: 'text',
          selector: 'label',
        },
      ],
      attrs: {
        body: {
          stroke: '#5F95FF',
          fill: '#5F95FF',
        },
        image: {
          width: 26,
          height: 26,
          refX: 13,
          refY: 16,
        },
        label: {
          refX: 3,
          refY: 2,
          textAnchor: 'left',
          textVerticalAnchor: 'top',
          fontSize: 12,
          fill: '#fff',
        },
      },
      ports: { ...ports },
    },
    true,
  )
}
registerNode()
// export const generateNodeData = (type)=> {
//   return {
//     id: 'node1',
//     label: 'Node 1',
//     x: Math.random() * 100,
//     y: Math.random() * 100,
//     size: Math.random() * 50 + 10,
//     color: '#ff0000',
//     shape: type || 'rect',
//   }
// }